package insight.google.game.era.bo;

import insight.google.game.era.bo.GameUser;

import insight.google.game.era.bo.card.CharacterCard;
import insight.google.game.era.bo.card.GameCard;
import insight.google.game.era.bo.card.RoleCard;
import insight.google.game.era.bo.policy.PolicyCenter;
import insight.google.game.era.bo.policy.PolicyFactory;
import insight.google.game.era.bo.policy.character.CharacterPolicy;
import insight.google.game.era.client.proxy.ChatClientProxyImpl;
import insight.google.game.era.client.proxy.HostClientProxyImpl;
import insight.google.game.era.client.proxy.PlayerClientProxy;
import insight.google.game.era.client.proxy.PlayerClientProxyImpl;
import insight.google.game.era.client.proxy.RoomClientProxy;
import insight.google.game.era.client.proxy.RoomClientProxyImpl;
import insight.google.game.era.core.ChatCenter;
import insight.google.game.era.core.ChatCenterServiceProvider;
import insight.google.game.era.core.Util;
import insight.google.game.era.core.cache.AppCacheManager;
import insight.google.game.era.core.cache.GameCacheManager;
import insight.google.game.era.core.exception.InsightException;
import insight.google.game.era.core.hub.HubServiceManager;
import insight.google.game.era.core.hub.PendingEvents;
import insight.google.game.era.core.hub.UserEvents;
import insight.google.game.era.data.AppDataManagerFactory;
import insight.google.game.era.data.BaseData;
import insight.google.game.era.data.DataStoreManager;
import insight.google.game.era.data.GameCenterDataManager;
import insight.google.game.era.data.GameHistory;
import insight.google.game.era.data.RoomHistory;
import insight.google.game.era.data.GameHistoryDetail;
import insight.google.game.era.data.RoomDataManager;
import insight.google.game.era.data.GameUserDataManager;
import insight.google.game.era.data.TransactionHandler;
import insight.google.game.era.data.User;
import insight.google.game.era.data.UserDataManager;
import insight.google.game.era.mgr.FlowManager;
import insight.google.game.era.mgr.GameLogManager;
import insight.google.game.era.service.RoomServiceImpl;
import insight.google.game.era.data.AppDataManagerFactory.DataManager;
import insight.google.game.era.data.policys.Policy;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.jdo.annotations.Element;
import javax.jdo.annotations.FetchGroup;
import javax.jdo.annotations.FetchPlan;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.NotPersistent;
import javax.jdo.annotations.NullValue;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

import org.apache.commons.logging.LogFactory;
import org.directwebremoting.annotations.DataTransferObject;
import org.directwebremoting.annotations.RemoteProperty;
import org.apache.commons.logging.Log;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
@DataTransferObject
// @FetchGroup(name = "room_user_list", members = {
// @Persistent(name = "userList"), @Persistent(name = "gameLogManager") })
// @FetchPlan(fetchSize = 1, fetchGroups = "room_user_list")
public class GameRoom extends BaseData implements Room,
		ChatCenterServiceProvider {

	private static final Log log = LogFactory.getLog(GameRoom.class);
	private static final int MIN_USERS = 2;
	private static final int MAX_USERS = 8;
	public static final int TOTALNOOF_ROOMS = 10;
	private static final int NO_OF_INITIAL_CARDS = 4;
	private static final int NO_OF_START_CARDS = 4;

	private static final long MAX_HANG_ROOM_WAITING = 45000;

	public static final String[] initActiveCards = { "arm", "attack" };
	public static final String[] allActiveCards = { "arm", "base" };

	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	@PrimaryKey
	private Key roomId;

	@RemoteProperty
	@Persistent
	private String roomName;

	@RemoteProperty
	@Persistent(mappedBy = "currentRoom", defaultFetchGroup = "true")
	private List<GameUser> userList = new ArrayList<GameUser>();

	@Persistent
	private long dataVersion = 0;

	@Persistent
	private String jsComponentId = "room_instance";

	@RemoteProperty
	@Persistent
	private String ownerName;

	@RemoteProperty
	@Persistent
	private int gameState = INITIALIZED;

	@Persistent(defaultFetchGroup = "true")
	private GameLogManager gameLogManager;

	@Persistent
	private Key kingUserId = null;

	@NotPersistent
	List<GameCard> gameCardDeck;

	@Persistent
	List<String> gameCardDeckIdList;

	@Persistent
	Key currentUserId;

	@Persistent
	private int gameCardCounter = 0;

	@Persistent(defaultFetchGroup = "true")
	private GameUser hangUser = null;

	@Persistent(mappedBy = "currentRoom", defaultFetchGroup = "true")
	private List<Task> taskList = null;// new ArrayList<Task>();

	@Persistent
	private Key chatCenterId;

	@Persistent
	private long lastModifiedDate = (new Date()).getTime();

	public GameRoom(String roomName) {
		this.roomName = roomName;
		dataVersion = 0;
	}

	@NotPersistent
	private GameUser kingUser = null;

	public boolean join(GameUser gameUser) {

		gameUser.setCurrentRoom(this);

		// gameUser.initForNewGame();
		// log.debug("Owner name of " + this.roomName + " is " +
		// this.ownerName);
		if (this.getOwnerName() == null) {
			this.init(gameUser);
		}
		this.addUser(gameUser);
		try {
			this.upgradeDataVersion();
			// this.publicData(gameUser);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return true;
	}

	public void init(GameUser owner) {
		this.ownerName = owner.getName();
		this.gameLogManager = new GameLogManager(this);
		this.initChatCenter();
		log.debug(this.gameLogManager + "  is the game log manager for room "
				+ this.roomName);
	}

	public void addUser(GameUser user) {
		if (this.isUserExist(user.getName())) {
			return;
		}
		log.debug("USER JOINED ROOOM --   " + user.getName());
		userList.add(user);
		gameLogManager.addGameLog(new GameActionLog(user.getName()
				+ " has Joined "));

		if (userList.size() >= MAX_USERS) {
			this.gameState = NOW_MAX_USER;
		} else if (userList.size() >= MIN_USERS) {
			this.gameState = READY_FOR_START;
		}

	}

	public boolean isUserExist(String userName) {
		boolean retVal = false;
		for (GameUser user : this.userList) {
			if (user.getName().equals(userName)) {
				retVal = true;
			}
		}
		return retVal;
	}

	public void initGameRoomForClient(String jsComponentId, User currUser) {
		this.jsComponentId = jsComponentId;
		RoomClientProxyImpl.getInstance().doRoomInit(currUser.getScriptProxy(),
				jsComponentId, this, this.getDataVersion());
		for (GameUser user : this.userList) {
			if (user.getName().equals(currUser.getName())) {
				user.setScriptProxy(currUser.getScriptProxy());
			}
		}

		gameLogManager.broadcastGameActionLog();

	}

	@RemoteProperty
	public String getUserName() {
		User currUser = Util.getUserBySession();
		return currUser != null ? currUser.getName() : null;
	}

	public Key getRoomId() {
		return roomId;
	}

	public void setRoomId(Key roomId) {
		this.roomId = roomId;
	}

	public String getRoomName() {
		return roomName;
	}

	public void setRoomName(String roomName) {
		this.roomName = roomName;
	}

	public List<GameUser> getUserList() {
		return userList;
	}

	public void setUserList(List<GameUser> userList) {
		this.userList = userList;
	}

	public long getDataVersion() {
		return dataVersion;
	}

	public void setDataVersion(long dataVersion) {
		this.dataVersion = dataVersion;
	}

	public String getJsComponentId() {
		return jsComponentId;
	}

	public void setJsComponentId(String jsComponentId) {
		this.jsComponentId = jsComponentId;
	}

	public String getOwnerName() {
		return ownerName;
	}

	public void setOwnerName(String ownerName) {
		this.ownerName = ownerName;
	}

	public int getGameState() {
		return gameState;
	}

	public void setGameState(int gameState) {
		this.gameState = gameState;
	}

	public long getLastModifiedDate() {
		return lastModifiedDate;
	}

	public void setLastModifiedDate(long lastModifiedDate) {
		this.lastModifiedDate = lastModifiedDate;
	}

	public Key getChatCenterId() {
		return chatCenterId;
	}

	public void setChatCenterId(Key chatCenterId) {
		this.chatCenterId = chatCenterId;
	}

	@Override
	public void pause() {
		// TODO Auto-generated method stub

	}

	@Override
	public void showScore() {
		// TODO Auto-generated method stub

	}

	@Override
	public void stop() {
		// TODO Auto-generated method stub

	}

	public GameLogManager getGameLogManager() {
		return gameLogManager;
	}

	// public void setGameLogManager(GameLogManager gameLogManager) {
	// this.gameLogManager = gameLogManager;
	// }

	@Override
	public boolean notifyUserQuit(GameUser user) throws InsightException {
		// if user state is player then remove user from room only
		// if user state is dead calculate winner and keep user in list as dead
		log.debug(" user   ---  " + user);
		if (user.getState() == GameUser.STATE_USER) {
			gameLogManager.addGameLog(new GameActionLog(user.getName()
					+ " has leave the room"));
		} else if (user.getState() == GameUser.STATE_QUIT_AFTER_GAME_STARTED) {
			gameLogManager.addGameLog(new GameActionLog(user.getName()
					+ " quit from room , he is dead for this game"));

		} else if (user.getState() == GameUser.STATE_DEAD) {
			gameLogManager.addGameLog(new GameActionLog(user.getName()
					+ " is dead"));

		}
		if (user.getState() != GameUser.STATE_DEAD) {
			this.userList.remove(user);
		}
		if (this.gameState == STARTED) {
			List<GameUser> winners = this.getWinner();
			if (winners.size() > 0) {
				this.publishGameResult(winners);
				this.setGameState(GAME_OVER);
			}
		}

		try {
			this.publicData(user);
			log.debug("room version data  ###   " + this.dataVersion);
		} catch (InsightException e) {
			e.printStackTrace();
		}
		log.debug("After removing user  " + user.getName()
				+ "   usetlist size is " + userList.size());

		if (gameLogManager != null) {
			gameLogManager.broadcastGameActionLog();
		}

		return true;
	}

	private List<GameUser> getWinner() {
		HashMap<String, GameUser> usersAlive = this.getAliveUsers();
		List<GameUser> winners = new ArrayList<GameUser>();

		/* if Rebel wins */
		if (!usersAlive.containsKey(RoleCard.KING)
				&& (usersAlive.containsKey(RoleCard.REBEL + "1") || usersAlive
						.containsKey(RoleCard.REBEL + "2"))) {
			if (usersAlive.containsKey(RoleCard.REBEL + "1")) {
				winners.add(usersAlive.get(RoleCard.REBEL + "1"));
			}
			if (usersAlive.containsKey(RoleCard.REBEL + "2")) {
				winners.add(usersAlive.get(RoleCard.REBEL + "2"));
			}
		}
		if (!usersAlive.containsKey(RoleCard.KING)
				&& !usersAlive.containsKey(RoleCard.REBEL + "1")
				&& !usersAlive.containsKey(RoleCard.REBEL + "2")) {
			if (usersAlive.containsKey(RoleCard.SUPPORTER + "1")) {
				winners.add(usersAlive.get(RoleCard.SUPPORTER + "1"));
			}
			if (usersAlive.containsKey(RoleCard.SUPPORTER + "2")) {
				winners.add(usersAlive.get(RoleCard.SUPPORTER + "2"));
			}
		}
		/* if Traitor wins */
		if (!usersAlive.containsKey(RoleCard.KING)
				&& !usersAlive.containsKey(RoleCard.REBEL + "1")
				&& !usersAlive.containsKey(RoleCard.REBEL + "2")
				&& !usersAlive.containsKey(RoleCard.SUPPORTER + "1")
				&& !usersAlive.containsKey(RoleCard.SUPPORTER + "2")) {
			if (usersAlive.containsKey(RoleCard.TRAITOR + "1")) {
				winners.add(usersAlive.get(RoleCard.TRAITOR + "1"));
			}
			if (usersAlive.containsKey(RoleCard.TRAITOR + "2")) {
				winners.add(usersAlive.get(RoleCard.TRAITOR + "2"));
			}
		}

		if (usersAlive.containsKey(RoleCard.KING)
				&& !(usersAlive.containsKey(RoleCard.REBEL + "1") || usersAlive
						.containsKey(RoleCard.REBEL + "2"))
				&& !(usersAlive.containsKey(RoleCard.TRAITOR + "1"))
				&& !(usersAlive.containsKey(RoleCard.TRAITOR + "2"))) {
			if (usersAlive.containsKey(RoleCard.KING)) {
				winners.add(usersAlive.get(RoleCard.KING));
			}
			if (usersAlive.containsKey(RoleCard.SUPPORTER + "1")) {
				winners.add(usersAlive.get(RoleCard.SUPPORTER + "1"));
			}
			if (usersAlive.containsKey(RoleCard.SUPPORTER + "2")) {
				winners.add(usersAlive.get(RoleCard.SUPPORTER + "2"));
			}
		}
		return winners;
	}

	private HashMap<String, GameUser> getAliveUsers() {
		HashMap<String, GameUser> usersAlive = new HashMap<String, GameUser>();
		for (GameUser gameUser : userList) {
			if (gameUser.getState() != GameUser.STATE_DEAD) {
				if (gameUser.getState() == GameUser.STATE_QUIT_AFTER_GAME_STARTED) {
					continue;
				}
				usersAlive.put(gameUser.getRoleCard().getId(), gameUser);
			}
		}
		return usersAlive;
	}

	private void publishGameResult(List<GameUser> winners) {
		List<Map> resultMap = this.getResult(winners);
		for (GameUser gameUser : userList) {

			if (gameUser.getScriptProxy() != null) {
				// RoomClientProxyImpl.getInstance().showGameResult(
				// gameUser.getScriptProxy(), this.jsComponentId, winners);
				RoomClientProxyImpl.getInstance().showGameResult(
						gameUser.getScriptProxy(), this.jsComponentId,
						resultMap);
			} else {

				GameCacheManager gameCache = new GameCacheManager();
				gameCache.addToCache(gameUser.getEmail(), resultMap);
			}

		}
		gameState = INITIALIZED;
	}

	private List<Map> getResult(List<GameUser> winners) {
		HashMap<String, String> resultUser = null;
		List<Map> resultMap = new ArrayList<Map>();
		for (GameUser gameUser : winners) {
			resultUser = new HashMap<String, String>();
			resultUser.put("name", gameUser.getName());
			resultUser.put("roleCardName", gameUser.getRoleCard().getName());
			resultMap.add(resultUser);
		}
		return resultMap;
	}

	@Override
	public boolean sendCard(String jsId, GameUser currUser, String[] targets,
			String cardId) throws InsightException {
		// TODO Auto-generated method stub

		GameCard card = currUser.findCardByGenratedId2(currUser
				.getDataManager(), cardId);
		if (card == null) {
			System.out.println("error is output: card is null, card id is "
					+ cardId);
		}
		HashMap params = new HashMap();
		params.put("cardName", card.getName());
		params.put("jsComponenetId", jsId);
		GameUser[] tagUsers = new GameUser[targets.length];
		int index = 0;
		HashMap<String, GameCard> data = new HashMap<String, GameCard>();

		for (GameUser user : userList) {
			for (int i = 0; i < targets.length; i++) {
				if (user.getName().equals(targets[i])) {
					tagUsers[index] = user;
					//user.setRecievedPLayedCard(card.getDisplayName());
					data.put(user.getName(), card);
					index++;
				}
			}
			if (!card.getCardType().equals("arm")) {
				// user.notifyPlayedCard(data);
			}
		}
		card.execute(currUser, tagUsers, params);

		// remove card from user's card list
		currUser.removeCard(card.getId());

		return true;
	}

	@Override
	public boolean upgradeDataVersion() throws InsightException {
		this.dataVersion++;
		this.lastModifiedDate = (new Date()).getTime();
		return true;
	}

	@Override
	public void sendChatMessage(String msg, String jsComponentId) {
		// TODO Auto-generated method stub

	}

	public void processVersionConflict(int version, User user) {
		if (this.dataVersion > version) {
			RoomClientProxyImpl.getInstance().doRoomRefresh(
					user.getScriptProxy(), this.jsComponentId, this,
					this.dataVersion);
			RoomDataManager roomDataManager = new RoomDataManager();
			ChatCenter chatCenter = roomDataManager
					.findChatCenterById(this.chatCenterId);
			if (chatCenter != null) {
				ChatClientProxyImpl.getInstance().showChatMessage(
						user.getScriptProxy(), chatCenter.getJsComponentId(),
						chatCenter.getAllMessages());
			}

		} else if (this.dataVersion == version && this.gameState == STARTED) {
			Date now = new Date();
			if ((now.getTime() - this.getLastModifiedDate()) > MAX_HANG_ROOM_WAITING) {
				// force current user to quit
				// Key currentUserId = this.getCurrentUserId();
				if (this.currentUserId != null) {
					UserDataManager userDataManager = new UserDataManager();
					User currPlayer = userDataManager
							.findById(this.currentUserId);
					if (currPlayer != null) {
						(new RoomServiceImpl()).quitFromRoom(true, currPlayer);
					}
				}
			}
		}

	}

	@RemoteProperty
	public List<GameActionLog> getGameLogList() {
		if (gameLogManager != null && gameLogManager.getRoomLogList() != null) {
			return gameLogManager.getRoomLogList();
		}
		return null;
	}

	@Override
	public boolean discardCharacterCards(User currUser) throws InsightException {
		// TODO Auto-generated method stub
		try {
			// Collection<GameUser> players = userList.values();
			HashMap<String, Object> data = null;

			List<CharacterCard> characters = CharacterCard
					.getCharacterCard(userList.size());
			int index = 0;
			log.debug("CHARACTER CARDS size  ---   " + characters.size());
			for (GameUser user : userList) {
				CharacterCard character = characters.get(index);
				if (currUser.getName().equals(user.getName())) {
					user.setScriptProxy(currUser.getScriptProxy());
				}
				user.setCharacterCard(character);// characters.get(randomCardIndex(roleCards.size()-1)));
				index++;
				if (!currUser.getName().equals(user.getName())
						&& currUser.getScriptProxy() != null) {
					PlayerClientProxyImpl.getInstance()
							.showCharacterCardToUser(currUser.getScriptProxy(),
									jsComponentId, user);
				}
				// execute selected policy
				List<Integer> chaPolicy = character.getPolicyList();
				int type = 0;
				for (int policyId : chaPolicy) {
					Policy policy = PolicyFactory.getInstance(policyId);
					if (policy instanceof CharacterPolicy) {
						type = ((CharacterPolicy) policy).getType();
						if (type == CharacterPolicy.TYPE_BE_SELECTED) {
							GameUser[] userListTmp = new GameUser[1];
							userListTmp[0] = user;
							((CharacterPolicy) policy).beSelectedExec(user,
									userListTmp, null);
						}
					}
				}
				gameLogManager.addGameLog(new GameActionLog(
						"Character card is distributed to " + user.getName()));
				gameLogManager.broadcastGameActionLog();

			}
			this.publicData(currUser);
			log.debug("room version data  ###   " + this.dataVersion);
			// AppDataManagerFactory.getInstance().getDataManager(
			// DataManager.ROOM_DATA_MANAGER.toString()).addToDataStore(
			// this);
		} catch (InsightException e) {
			e.printStackTrace();
		} finally {
		}

		return true;
	}

	@Override
	public boolean discardRoleCard(User currUser) throws InsightException {
		// TODO Auto-generated method stub

		try {
			HashMap<String, Object> data = null;
			this.gameState = STARTED;
			/*
			 * Select role cards for userList depending on no. of userList there
			 * should be one King must
			 */
			List<RoleCard> roleCards = RoleCard.getRoleCards(userList.size());
			log.debug("ROLE CARDS size  ---   " + roleCards.size());
			GameUser kingUser = null;
			int index = 0;

			for (GameUser user : userList) {
				if (currUser.getName().equals(user.getName())) {
					user.setScriptProxy(currUser.getScriptProxy());
				}
				user.setRoleCard(roleCards.get(index));// roleCards.get(randomCardIndex(roleCards.size()-1)));
				index++;
				if (user.getRoleCard().getName().equals(RoleCard.KING)) {
					kingUser = user;
					this.kingUserId = user.getId();
				}
				gameLogManager.addGameLog(new GameActionLog(
						"Role card is distributed to " + user.getName()));
				gameLogManager.broadcastGameActionLog();
			}
			// // GameCenter.getInstance().broadCastUsers("",
			// // "mainframe_instance");
			// //
			// gameLogManager.addGameLog(new GameActionLog(
			// "Role card is distributed to everybody"));
			// gameLogManager.broadcastGameActionLog();
			// //

			this.publicData(currUser);
			log.debug("room version data  ###   " + this.dataVersion);
			// AppDataManagerFactory.getInstance().getDataManager(
			// DataManager.ROOM_DATA_MANAGER.toString()).addToDataStore(
			// this);
		} catch (InsightException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return true;
	}

	public boolean publicData(User user) throws InsightException {
		try {
			this.upgradeDataVersion();
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (user.getScriptProxy() != null) {
			RoomClientProxyImpl.getInstance().publicDataVersion(
					user.getScriptProxy(), this.jsComponentId,
					this.getDataVersion());
		}
		return false;
	}

	@Override
	public boolean publicData(GameUser user) throws InsightException {
		try {
			this.upgradeDataVersion();
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (user.getScriptProxy() != null) {
			RoomClientProxyImpl.getInstance().publicDataVersion(
					user.getScriptProxy(), this.jsComponentId,
					this.getDataVersion());
		}
		return false;
	}

	public void quit(User user) {
		GameUser currUser = Util.getUserByNameAndRoom(this, user);
		currUser.setScriptProxy(user.getScriptProxy());
		currUser.quitRoom();
		this.removedRoomOwner(currUser);

		try {
			this.notifyUserQuit(currUser);
		} catch (InsightException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// this.getGameUserDataManager().addToDataStore(user);
		if (this.gameState == READY_FOR_START && userList.size() < MIN_USERS) {
			this.gameState = INITIALIZED;
		}
	}

	private void removedRoomOwner(GameUser currUser) {
		if (this.ownerName != null && currUser.getName().equals(this.ownerName)) {
			this.ownerName = null;
			for (GameUser user : this.userList) {
				if (!user.getName().equals(currUser.getName())) {
					this.ownerName = user.getName();
					return;
				}
			}
		}
	}

	@Override
	public boolean publicData(User user, long dataVersion)
			throws InsightException {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean finishPlay(GameUser user) throws InsightException {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean gameOver(GameUser user) throws InsightException {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean start(GameUser user) throws InsightException {
		// TODO Auto-generated method stub
		return false;
	}

	public boolean checkDataVersion(long dataVersion) {
		return false;
	}

	public void shuffuleCards() {
		this.loadGameCardDeck();
	}

	private void loadGameCardDeck() {
		List<GameCard> allInitCards = GameCard.getInitGameCards();
		this.gameCardDeck = new ArrayList<GameCard>(allInitCards);
		for (GameCard card : allInitCards) {
			this.gameCardDeckIdList.add(card.getId());
		}
	}

	public void discardCard2All(GameRoom gRoom, User currUser,
			GameUserDataManager gameUserDataManager) {
		for (GameUser user : this.userList) {
			user.initUserForGame(this.initialCards(NO_OF_INITIAL_CARDS));

			List<String> attackableUsers = this.getAttackableUserList(user);
			user.setAttackUserList(attackableUsers);
			user.setRegisterAttack(true);

			if (currUser.getName().equals(user.getName())) {
				user.setScriptProxy(currUser.getScriptProxy());
				PlayerClientProxyImpl.getInstance().dispatchCard(
						user.getScriptProxy(), jsComponentId,
						user.getGameCards2(gameUserDataManager));

				user.registerAttackableUser2("current_player_instance",
						gameUserDataManager);
				user.setRegisterAttack(false);
			}
		}
	}

	private ArrayList<GameCard> initialCards(int cardCount) {
		ArrayList<GameCard> gameCards = new ArrayList<GameCard>();

		if (this.gameCardDeck == null) {
			this.checkAndSetGameCard();
		}
		for (int i = 0; i < cardCount; i++) {
			gameCards.add(gameCardDeck.get(this.gameCardCounter));
			this.gameCardCounter++;
			if (this.gameCardCounter >= gameCardDeck.size()) {
				this.gameCardCounter = 0;
			}
		}

		return gameCards;
	}

	private void checkAndSetGameCard() {
		if (this.gameCardDeck == null && this.gameCardDeckIdList != null) {
			this.gameCardDeck = new ArrayList<GameCard>();
			for (String cardId : this.gameCardDeckIdList) {
				this.gameCardDeck.add(GameCard.getGameCardById(cardId));
			}
		}
	}

	public List<String> getAttackableUserList(GameUser orgUser) {
		List<String> userList = new ArrayList<String>();
		Collection<GameUser> attackUsers = this.getAttackableUsers(orgUser);
		for (GameUser user : attackUsers) {
			userList.add(user.getName());
		}
		return userList;
	}

	public Collection<GameUser> getAttackableUsers(GameUser orgUser) {
		List<GameUser> attackList = new ArrayList<GameUser>();
		List<GameUser> userList1 = new ArrayList<GameUser>();
		// check user's active
		for (GameUser user : userList) {
			if (GameUser.STATE_DEAD != user.getState()) {
				userList1.add(user);
			}
		}
		int distance = orgUser.getAttackDistance();
		int location = 0;
		int lenList = userList1.size();
		for (int i = 0; i < lenList; i++) {
			if (userList1.get(i).getId().equals(orgUser.getId())) {
				location = i;
				break;
			}
		}
		int index = 0;
		for (int i = 1; i <= distance; i++) {
			// get attack user's index
			index = location + i;
			if (location + i >= lenList) {
				index = location + i - lenList;
			}
			// compare the user's defend distance with attack distance to check
			// can attack or not.
			if ((distance - i) >= userList1.get(index).getDefendDistance()) {
				attackList.add(userList1.get(index));
			}
		}
		for (int i = 1; i <= distance; i++) {
			index = location - i;
			if (location - i < 0) {
				index = location - i + lenList;
			}
			// compare the user's defend distance with attack distance to check
			// can attack or not.
			if ((distance - i) >= userList1.get(index).getDefendDistance()) {
				if (!attackList.contains(userList1.get(index))) {
					attackList.add(userList1.get(index));
				}
			}
		}
		return attackList;
	}

	public void setKingUser(GameUser kingUser) {
		this.kingUser = kingUser;
	}

	public GameUser getKingUser() {
		return this.getGameUserDataManager().findById(this.kingUserId);
		// return kingUser;
	}

	public Key getKingUserId() {
		return kingUserId;
	}

	public void setKingUserId(Key kingUserId) {
		this.kingUserId = kingUserId;
	}

	private GameUserDataManager getGameUserDataManager() {
		return (GameUserDataManager) AppDataManagerFactory.getInstance()
				.getDataManager(DataManager.GAMEUSER_DATA_MANAGER.toString(),
						Util.createTranscationHandler());
	}

	public ArrayList<GameCard> getStartCard(int count) {
		return this.initialCards(count);

	}

	public void putTask(GameUser orgUser, GameUser trgUser,
			String originalCard, String matchValue) {
		this.taskList.add(new Task(this, orgUser.getName(), trgUser.getName(),
				originalCard, matchValue));
		// AppDataManagerFactory.getInstance().getDataManager(
		// DataManager.ROOM_DATA_MANAGER.toString()).addToDataStore(this);
	}

	public void removeTask(int index) {
		if (taskList.size() > index) {
			taskList.remove(index);
			// AppDataManagerFactory.getInstance().getDataManager(
			// DataManager.ROOM_DATA_MANAGER.toString()).addToDataStore(this);
		}
	}

	public List<Task> getTaskList() {
		return this.taskList;
	}

	public void removeUserTask(String userName) {
		for (Task task : this.taskList) {
			String trgUser = task.getTargetUserName();
			if (trgUser.equals(userName)) {
				taskList.remove(task);
				// AppDataManagerFactory.getInstance().getDataManager(
				// DataManager.ROOM_DATA_MANAGER.toString()).addToDataStore(this);
			}
		}
	}

	public boolean failToDoMatchCard(GameRoom room, GameUser currUser,
			String jsId, String cardName) {
		HashMap params = new HashMap();
		params.put("jsComponenetId", jsId);
		// GameUser currUser = Util.getUserByRoom(this);
		PolicyCenter pCenter = PolicyCenter.getInstance();
		return pCenter.failToMatchCard(currUser, room, params);
	}

	public GameUser getGameUserByNameFromList(String userName) {
		for (GameUser user : this.userList) {
			if (user.getName().equals(userName)) {
				return user;
			}
		}
		return null;
	}

	public void checkActiveHangeUser(int version, GameUser user) {
		RoomClientProxyImpl.getInstance().activeHangUser(user.getScriptProxy(),
				this.jsComponentId);
	}

	public GameUser getHangUser() {
		return hangUser;
	}

	public void setHangUser(GameUser hangUser) {
		this.hangUser = hangUser;
	}

	public List<GameCard> getCardsByCardCount(int cardCnt) {
		int noOfCards = 1;
		List<GameCard> rtnCards = new ArrayList<GameCard>();
		if (this.gameCardDeck != null && !this.gameCardDeck.isEmpty()) {
			Random rnd = new Random();
			for (int i = 0; i < cardCnt; i++) {
				GameCard card = gameCardDeck.remove(rnd.nextInt(gameCardDeck
						.size() - 1));
				rtnCards.add(card);
			}

		}
		return rtnCards;
	}

	public GameCard getCardByCardName(String cardName) {
		GameCard rtnCard = null;
		if (this.gameCardDeck != null && !this.gameCardDeck.isEmpty()) {
			for (GameCard card : gameCardDeck) {
				if (card.getName().equals(cardName)) {
					rtnCard = card;
					break;
				}
			}
		} else {
			return GameCard.getGameCardByName(cardName);
		}
		return rtnCard;
	}

	public void sendCardToUserByCardName(GameUser tagUser, String cardName) {
		GameCard card = this.getCardByCardName(cardName);
		List<GameCard> cardList = new ArrayList<GameCard>();
		if (card != null) {
			cardList.add(card);
			tagUser.addGameCard(card);
			if (tagUser.getScriptProxy() != null) {
				PlayerClientProxyImpl.getInstance().recievePlayerCard(
						tagUser.getScriptProxy(), this.jsComponentId, cardList);
			} else {
			}
		}
	}

	public void sendCardToUserByCards(GameUser tagUser, String[] cards) {
		List<GameCard> cardList = new ArrayList<GameCard>();
		for (int i = 0; i < cards.length; i++) {
			GameCard card = this.getCardByCardName(cards[i]);
			if (card != null) {
				cardList.add(card);
				tagUser.addGameCard(card);
			}
		}

		if (!cardList.isEmpty()) {
			if (tagUser.getScriptProxy() != null) {
				PlayerClientProxyImpl.getInstance().recievePlayerCard(
						tagUser.getScriptProxy(), this.jsComponentId, cardList);
			} else {
			}
		}
	}

	public void sendCardToUserByCount(GameUser tagUser, int count) {
		List<GameCard> cardList = this.getCardsByCardCount(count);
		if (cardList != null && !cardList.isEmpty()) {
			for (GameCard card : cardList) {
				tagUser.addGameCard(card);
			}
			if (tagUser.getScriptProxy() != null) {
				PlayerClientProxyImpl.getInstance().recievePlayerCard(
						tagUser.getScriptProxy(), this.jsComponentId, cardList);
			}
		}
	}

	private ChatCenter initChatCenter() {
		ChatCenter chatCenter = null;
		RoomDataManager roomDataManager = null;
		try {
			chatCenter = new ChatCenter(null, this.roomName);
			chatCenter.setJsComponentId("chatMsgListModelRoom_instance");
			roomDataManager = new RoomDataManager(Util
					.createTranscationHandler());
			roomDataManager.addToDataStore(chatCenter);
			roomDataManager.commit();
			roomDataManager = new RoomDataManager();
			chatCenter = roomDataManager.findChatCenter(ChatCenter.HOST_ROOM,
					this.roomName);
			this.chatCenterId = chatCenter.getId();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (roomDataManager != null) {
				roomDataManager.close();
			}

		}
		return chatCenter;
	}

	public Key getCurrentUserId() {
		return currentUserId;
	}

	public void setCurrentUserId(Key currentUserId) {
		this.currentUserId = currentUserId;
	}

}
